package org.jobtask.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerDateModel;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.jobtask.config.SystemIdentification;
import org.jobtask.schedule.JobTask;
import org.jobtask.schedule.KeyValue;


/**
 * 
 * @author Bob Coyote 
 * 描述: 本类继承了JDialog
 *
 */
public class TaskEditDialog extends JDialog{

	
	private static String currentDir;
	static{currentDir=System.getProperty("home.dir");}
	
	/**
	 * 任务文件浏览部分的组件
	 * ===============================================
	 */
	//浏览任务文件的按钮,点击以后会打开一个文件对话框
	private JButton searchBut;
	//任务名称
	private JTextField taskNameTxt;
	//任务文件的文件路径
	private JTextField pathTxt;
	/**..,,
	 * ===============================================
	 */
	
	
	
	/**
	 * 重复任务部分的组件
	 * ===============================================
	 */
	//重复任务的选择框
	private JRadioButton repeatRadio;
	//输入重复次数的文本域
	private JTextField countTxt;
	//输入间隔时间的文本域.单位 秒(m)
	private JTextField intervalTxt;
	/**
	 * ==============================================
	 */
	
	//用于将单选按钮归为一组
	private ButtonGroup groupBut;
	
	/**
	 * 定时任务部分的组件
	 * ==============================================
	 */
	//定时任务的选择框
	private JRadioButton timerRadio;
	//运行方式选择,配给定时任务
	private JComboBox methodSelect;
	//启动时间序列,配给定时任务,可以同时指定多个时间点
	private JComboBox startTimesSelect;
	//定时时间添加按钮
	private JButton addTimeBut;
	//定时时间移除按钮
	private JButton delTimeBut;
	//记录任务启动时间的微调器
	private JSpinner startTimeFine;
	/**
	 * ==============================================
	 */
	
	
	/**
	 * 对话框控制部分的组件
	 * =============================================
	 */
	//对话框的确定按钮
	private JButton okBut;
	//对话框的取消按钮
	private JButton cancelBut;
	/**
	 * =============================================
	 */
	
	
	private boolean clickState=false;
	
	private JobTask task=null;
	
	private DialogListener listener=null;
	
	public TaskEditDialog()
	{
		this.setTitle("添加新任务");
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setLayout(new BorderLayout());
		this.setModal(true);
		this.setSize(390,340);
		this.setResizable(false);
		this.setLocationRelativeTo(null);
		this.init();
	}
	
	
	private void init(){
		this.listener=new DialogListener();
		//===========浏览任务文件部分============
		this.pathTxt=new JTextField(20);
		this.pathTxt.setFont(UIConst.FONT14);
		this.taskNameTxt=new JTextField(24);
		this.taskNameTxt.setFont(UIConst.FONT14);
		this.searchBut=new JButton("浏览");
		this.searchBut.setFont(UIConst.FONT14);
		this.searchBut.addActionListener(listener);
		
		
		//===========重复任务设置部分============
		this.repeatRadio=new JRadioButton("重复");
		this.repeatRadio.setSelected(true);
		this.repeatRadio.setFont(UIConst.FONT14);
		this.repeatRadio.setToolTipText("等待任务完成以后,在间隔给定的时间后,再次启动任务");
		
		/**
		 * 设置格式化文本框的格式,标识只能输入数字
		 */
		this.countTxt=new JTextField();
		this.countTxt.setColumns(6);
		this.countTxt.setFont(UIConst.FONT14);
		this.countTxt.setText("0");
		this.countTxt.setToolTipText("输入重复次数,0或不填写则一直重复.");
		this.countTxt.addKeyListener(listener);
		this.intervalTxt=new JTextField();
		this.intervalTxt.setColumns(10);
		this.intervalTxt.setFont(UIConst.FONT14);
		this.intervalTxt.setText("0");
		this.intervalTxt.setToolTipText("任务间隔时间,不填写则为默认30秒.");
		this.intervalTxt.addKeyListener(listener);
		
		/**
		 * 给重复单选按钮添加监听事件
		 */
		this.repeatRadio.addItemListener(listener);
		
		
		//===========定时任务设置部分============
		/**
		 * 实例化按钮组对象
		 */
		this.groupBut=new ButtonGroup();
		
		this.timerRadio=new JRadioButton("定时");
		this.timerRadio.setToolTipText("在指定的时间开始运行");
		this.timerRadio.setFont(UIConst.FONT14);
		this.timerRadio.addItemListener(listener);
		
		/**
		 * 给任务运行方式的选项设置内容选项
		 */
		this.methodSelect=new JComboBox(new KeyValue[]{new KeyValue("one","一次  "),new KeyValue("day","每天  ")});
		this.methodSelect.setFont(UIConst.FONT14);
		
		/**
		 * 如果任务有多个时间点需要运行,该列表框将保存这些时间
		 */
		this.startTimesSelect=new JComboBox();
		this.startTimesSelect.setFont(UIConst.FONT14);
		
		/**
		 * 这里定义了将填写好的时间从选项框中加入/移除
		 */
		this.addTimeBut=new JButton("＋");
		this.addTimeBut.setToolTipText("添加定时时间到任务列表");
		this.addTimeBut.addActionListener(listener);
		this.delTimeBut=new JButton("－");
		this.delTimeBut.setToolTipText("从任务列表移除定时时间");
		this.delTimeBut.addActionListener(listener);
		
		/*
		 * 时间选择器,设置时间选择器的显示模式,这里使用日期时间模式
		 */
		SpinnerDateModel model = new SpinnerDateModel();
	    model.setCalendarField(Calendar.MINUTE);
	    this.startTimeFine=new JSpinner(model);
	    JSpinner.DateEditor dateEditor=new JSpinner.DateEditor(this.startTimeFine,"yyyy-MM-dd HH:mm:ss ");
	    this.startTimeFine.setEditor(dateEditor);
		this.startTimeFine.setFont(UIConst.FONT14);
		
		
		//===========对话框部分=================
		this.okBut=new JButton("   确定   ");
		this.cancelBut=new JButton("   取消   ");
		okBut.setFont(UIConst.FONT14);
		cancelBut.setFont(UIConst.FONT14);
		groupBut.add(repeatRadio);
		groupBut.add(timerRadio);
		this.okBut.addActionListener(listener);
		this.cancelBut.addActionListener(listener);
		
		/*
		 * 介面布局部分,带这个不后,所有的组件都应该实例化完成,按照顺序添加上层面板,中间层和下层
		 */
		
		/*
		 * 上层面板===============================
		 * 定义上层面板,他将包含所有要放入的组件和子面板
		 */
		JPanel topPanel=new JPanel(new BorderLayout());
		JPanel taskNamePanel=new JPanel();
		JPanel searchPanel=new JPanel();
		
		/*
		 * 放置任务名称的面板组件
		 */
		JLabel taskNameLab=new JLabel("任务名称:");
		taskNameLab.setFont(UIConst.FONT14);
		
		taskNamePanel.add(taskNameLab);
		taskNamePanel.add(this.taskNameTxt);
		
		/*
		 * 定义用于显示标题的标签,并设置它的显示字体
		 */
		JLabel searchLab=new JLabel("任务文件:");
		searchLab.setFont(UIConst.FONT14);
		/*
		 * 将设置好的标签和显示任务文件路径的文本框以及浏览按钮添加到searchPanel面板中
		 */
		searchPanel.add(searchLab);
		searchPanel.add(this.pathTxt);
		searchPanel.add(this.searchBut);
		
		topPanel.add(taskNamePanel,BorderLayout.PAGE_START);
		topPanel.add(searchPanel);
		
		/*
		 * 重复任务的面板==================================
		 * 这个面板用来放入重复任务的用户组件,将布局设置为方位
		 */
		JPanel innserpan=new JPanel(new BorderLayout());
		
		//首先将"重复"单选按钮放到面板的最上面
		innserpan.add(repeatRadio,BorderLayout.PAGE_START);
		/*
		 * 建立一个小面板,主要使用这个面板做一个框,来框住里面的组件,
		 * 主要是因为布局的方式,这个面板使用默认布局-流式布局,并设置了
		 * 面板的边框
		 */
		JPanel innserInputpan=new JPanel();
		innserInputpan.setBorder(BorderFactory.createTitledBorder("条件"));
		
		//建立次数标签,并设置显示字体
		JLabel countLab=new JLabel("次数:");
		countLab.setFont(UIConst.FONT14);
		
		//建立间隔标签,并设置显示字体
		JLabel intervalLab=new JLabel("       间隔:");
		intervalLab.setFont(UIConst.FONT14);
		
		//建立单位(秒)标签,并设置显示字体
		JLabel secondLab=new JLabel("秒(m)");
		secondLab.setFont(UIConst.FONT14);
		
		//将前面建立的标签和文本框加入到面板
		innserInputpan.add(countLab);
		innserInputpan.add(this.countTxt);
		innserInputpan.add(intervalLab);
		innserInputpan.add(this.intervalTxt);
		innserInputpan.add(secondLab);
		
		//将子面板添加到"重复任务"面板上
		innserpan.add(innserInputpan);
		
		//将顶部的面板和中间面板添加到本对话框中
		this.add(topPanel,BorderLayout.PAGE_START);
		this.add(innserpan,BorderLayout.CENTER);
		
		
		/*
		 * 计时任务的面板================================
		 * 这是一个放置在下方的面板,它包括定时任务的组件和对话框的
		 * 确定/取消按钮,分为上下两部分
		 */
		JPanel buttomPanel=new JPanel(new BorderLayout());
		
		/*
		 * 放置定时任务组件面板的面板
		 * 分为上下两部分
		 */
		JPanel timerPanel=new JPanel(new BorderLayout());
		
		/*
		 * 构建之间存放定时任务组件的面板,设置边框,由于组件需要分成两个部分来安装
		 * 所以面板也分为了上下两半
		 */
		JPanel innserTimePanel=new JPanel(new BorderLayout());
		innserTimePanel.setBorder(BorderFactory.createTitledBorder("条件"));
		
		/*
		 * 放置"启动时间"和运行方式下拉框,及添加任务时间删除任务时间的按钮
		 * 这是上面面板中的部分1
		 */
		JPanel innserPanel=new JPanel();
		JLabel startTimeLab=new JLabel("启动时间:");
		startTimeLab.setFont(UIConst.FONT14);
		innserPanel.add(startTimeLab);
		innserPanel.add(startTimeFine);
		innserPanel.add(this.methodSelect);
		innserPanel.add(this.addTimeBut);
		innserPanel.add(this.delTimeBut);
		//在innserTimePanel上添加第一部分
		innserTimePanel.add(innserPanel,BorderLayout.CENTER);
		
		
		/*
		 * 放置启动时间列表的下拉框,这是上面面板的部分2
		 */
		JPanel timeSelectPanel=new JPanel(new BorderLayout());
		JLabel taskListLab=new JLabel("  任务列表: ");
		taskListLab.setFont(UIConst.FONT14);
		timeSelectPanel.add(taskListLab,BorderLayout.LINE_START);
		timeSelectPanel.add(this.startTimesSelect);
		//在innserTimePanel上添加第二部分
		innserTimePanel.add(timeSelectPanel,BorderLayout.PAGE_END);
		
		/*
		 * 添加"定时"单选按钮
		 * 添加定时控件面板
		 */
		timerPanel.add(timerRadio,BorderLayout.PAGE_START);
		timerPanel.add(innserTimePanel);
		
		//默认不启用======
		this.startTimeFine.setEnabled(false);
		this.methodSelect.setEnabled(false);
		this.addTimeBut.setEnabled(false);
		this.delTimeBut.setEnabled(false);
		this.startTimesSelect.setEnabled(false);
		//===============
		
		//按钮面板
		JPanel butPanel=new JPanel();
		butPanel.add(this.okBut);
		butPanel.add(this.cancelBut);
		
		
		/*
		 * 在buttomPanel(计划任务面板)导航添加定时组件面板和对话框按钮
		 */
		buttomPanel.add(timerPanel,BorderLayout.PAGE_START);
		buttomPanel.add(butPanel,BorderLayout.PAGE_END);
		
		//将下方面板加入到对话框
		this.add(buttomPanel,BorderLayout.PAGE_END);
	}
	
	
	/**
	 * 打开对话框的方法
	 * @return 返回值为点击"确定"或"取消"的状态值
	 */
	public boolean openEditDialog(){
		this.setVisible(true);
		return this.clickState;
	}
	
	
	/**
	 * 打开对话框的方法
	 * @param task 根据传入的对象填充对话框
	 * @return 返回值为点击"确定"或"取消"的状态值
	 */
	public boolean openEditDialog(JobTask task){
		this.taskNameTxt.setText(task.getTaskName());
		this.pathTxt.setText(task.getTaskFile());
		if(task.getTaskType().equals("SCHEDULING.REPEAT")){
			this.repeatRadio.setSelected(true);
			this.countTxt.setText(task.getCount()+"");
			this.intervalTxt.setText(task.getInterval()+"");
		}else{
			this.timerRadio.setSelected(true);
			for(Iterator<Date> iter=task.getSartTimes().keySet().iterator();iter.hasNext();){
				Date date=iter.next();
				KeyValue kv=new KeyValue();
				kv.setKey(date);
				String k=task.getSartTimes().get(date);
				kv.setValue(new KeyValue(k,k.equals("one")?"一次":"每天"));
				this.startTimesSelect.addItem(kv);
			}
		}
		this.setVisible(true);
		return this.clickState;
	}
	
	/**
	 * 封装任务对象的方法,在对话框的确定按钮点击时调用
	 */
	public JobTask getJobTask(){
		return this.task;
	}
	
	
	/**
	 * 事件处理内部类
	 * 
	 */
	private class DialogListener implements ActionListener,ItemListener,KeyListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			if(e.getSource()==okBut){
				if(taskNameTxt.getText().trim().length()<=0){
					JOptionPane.showMessageDialog(TaskEditDialog.this, "请为您的任务起一个名字!", "提示",JOptionPane.WARNING_MESSAGE);
				}else if(pathTxt.getText().trim().length()<=0){
					JOptionPane.showMessageDialog(TaskEditDialog.this, "请选择一个任务文件,这很重要!", "提示",JOptionPane.WARNING_MESSAGE);
				}else if(!new File(pathTxt.getText().trim()).exists()){
					JOptionPane.showMessageDialog(TaskEditDialog.this, "请选择一个正确的任务文件!", "提示",JOptionPane.WARNING_MESSAGE);
				}else{
					builderJobTask();
					clickState=true;
					TaskEditDialog.this.dispose();
				}
			}
			if(e.getSource()==cancelBut){
				clickState=false;
				TaskEditDialog.this.dispose();
			}
			if(e.getSource()==searchBut){
				pathTxt.setText(searchFile());
			}
			if(e.getSource()==addTimeBut){
				addStartTimeToTaskList();
			}
			if(e.getSource()==delTimeBut){
				int index=startTimesSelect.getSelectedIndex();
				if(index>=0)
				startTimesSelect.removeItemAt(index);
			}
		}

		@Override
		public void itemStateChanged(ItemEvent e) {
			if(e.getSource()==repeatRadio){
				 resetRepeat(true);
				 resetTimer(false);
			}
			
			if(e.getSource()==timerRadio){
				resetRepeat(false);
				resetTimer(true);
			}
		}

		@Override
		public void keyTyped(KeyEvent e) {}

		@Override
		public void keyPressed(KeyEvent e) {}

		@Override
		public void keyReleased(KeyEvent e) {
			JTextField text=(JTextField)e.getSource();
			if(!text.getText().matches("\\d*")){
				 JOptionPane.showMessageDialog(TaskEditDialog.this, "这里一定要是一个数字哦!", "错误",JOptionPane.ERROR_MESSAGE);
				 text.setText("0");
			}else if(((JTextField)e.getSource()).getText().length()>9){
				JOptionPane.showMessageDialog(TaskEditDialog.this, "长度不能超过9位!", "错误",JOptionPane.ERROR_MESSAGE);
				text.setText(text.getText().substring(0,9));
			}
		}

	}
	
	private void  resetRepeat(boolean enable){
		this.countTxt.setEnabled(enable);
		this.intervalTxt.setEnabled(enable);
	}
	
	private void  resetTimer(boolean enable){
		this.startTimeFine.setEnabled(enable);
		this.methodSelect.setEnabled(enable);
		this.addTimeBut.setEnabled(enable);
		this.delTimeBut.setEnabled(enable);
		this.startTimesSelect.setEnabled(enable);
	}
	
	private String searchFile(){
		String[] extn=null;
		String descript="";
		JFileChooser fileDialog=new JFileChooser(currentDir);
		if(SystemIdentification.assertOS().equals("windows")){
			descript="支持文件(*.ktr,*.kjb,*.xml,*.bat,*.cmd,*.exe,*.jar)";
			extn=new String[]{"ktr","kjb","xml","bat","cmd","exe","jar"};
		}else if(SystemIdentification.assertOS().equals("linux")||SystemIdentification.assertOS().equals("unix")){
			descript="支持文件(*.ktr,*.kjb,*.xml,*.sh,*.job,*.jar)";
			extn=new String[]{"ktr","kjb","xml","sh","job","jar"};
		}else{
			 JOptionPane.showMessageDialog(TaskEditDialog.this, "程序目前还不支持您所使用的系统!", "错误",JOptionPane.ERROR_MESSAGE);
			 return null;
		}
		FileNameExtensionFilter fileFilter=new FileNameExtensionFilter(descript,extn); 
		fileDialog.setFileFilter(fileFilter);
		int option=fileDialog.showOpenDialog(TaskEditDialog.this);
		if(option==JFileChooser.APPROVE_OPTION){
			currentDir=fileDialog.getSelectedFile().getParent();
			return fileDialog.getSelectedFile().getPath();
		}else{
			return "";
		}
	}
	
	private void addStartTimeToTaskList(){
		KeyValue kv=new KeyValue();
		kv.setKey(startTimeFine.getValue());
		kv.setValue(methodSelect.getSelectedItem());
		boolean isContainer=false;
		for(int index=0;index<startTimesSelect.getItemCount();index++){
			KeyValue kt=(KeyValue)startTimesSelect.getItemAt(index);
			if(kt.getKey().equals(kv.getKey())){
				isContainer=true;
				break;
			}
		}
		if(!isContainer){
			startTimesSelect.addItem(kv);
			startTimesSelect.setSelectedItem(kv);
		}
	}
	
	private void builderJobTask(){
		task=new JobTask();
		task.setTaskName(this.taskNameTxt.getText());
		task.setTaskFile(this.pathTxt.getText().trim());
		if(this.repeatRadio.isSelected()){
			task.setCount(this.countTxt.getText().length()==0?0:new Integer(this.countTxt.getText()));
			task.setInterval(this.intervalTxt.getText().length()==0?0:new Integer(this.intervalTxt.getText()));
			task.setTaskType("SCHEDULING.REPEAT");
		}else if(this.timerRadio.isSelected()){
			for(int index=0;index<this.startTimesSelect.getItemCount();index++){
				KeyValue kv=(KeyValue)this.startTimesSelect.getItemAt(index);
				task.addStartTime((Date)kv.getKey(),((KeyValue)kv.getValue()).getKey().toString());
			}
			task.setTaskType("SCHEDULING.TIMER");
		}
	}
	
}
